package com.nowcoder.community.service;

import com.nowcoder.community.mapper.elasticsearch.DiscussPostRepository;
import com.nowcoder.community.pojo.DiscussPost;
import com.nowcoder.community.util.TimeUtil;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class ElasticsearchService {

    @Autowired
    private DiscussPostRepository discussPostRepository;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    public void saveDiscussPost(DiscussPost discussPost){
        discussPostRepository.save(discussPost);
    }

    public void deleteDiscussPost(int id){
        discussPostRepository.deleteById(id);
    }

    public Object[] searchDiscussPost(String keyword, int current, int limit) throws ParseException, IOException {

        Object[] objects = new Object[2];

        SearchRequest searchRequest = new SearchRequest("discuss_post");

        /*
        建立一个查询器。查询器的功能包括：
        从文档中的title字段和content字段中查询带有 关键词keyword 的文档，然后依次按照帖子类型（type）、
        帖子分数（score）以及帖子的创建时间（createTime）进行降序排序，同时还是分页查询
        并且在查出的帖子文档中将关键字显示为高亮。
        */
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder()
                .query(QueryBuilders.multiMatchQuery(keyword, "title", "content"))
                .sort(SortBuilders.fieldSort("type").order(SortOrder.DESC))
                .sort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
                .sort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
                .from(current)
                .size(limit)
                .highlighter(
                        new HighlightBuilder().field("title").preTags("<em>").postTags("</em>")
                                .field("content").preTags("<em>").postTags("</em>")
                );

        //通过查询器建立一个请求
        searchRequest.source(sourceBuilder);

        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        //获取所有的查询结果
        SearchHits hits = searchResponse.getHits();

        objects[1] = hits.getTotalHits().value;//获取搜索结果的总命中数
        //获取所有的查询结果
        SearchHit[] hitsHits = hits.getHits();

        if (hitsHits.length <= 0) {
            return objects;//此时数组为空数组
        }

        List<DiscussPost> list = new ArrayList<>();

        for (SearchHit hitsHit : hitsHits) {
            DiscussPost post = new DiscussPost();

            String id = hitsHit.getSourceAsMap().get("id").toString();
            post.setId(Integer.valueOf(id));

            String userId = hitsHit.getSourceAsMap().get("userId").toString();
            post.setUserId(Integer.valueOf(userId));

            String title = hitsHit.getSourceAsMap().get("title").toString();
            post.setTitle(title);

            String content = hitsHit.getSourceAsMap().get("content").toString();
            post.setContent(content);

            String type = hitsHit.getSourceAsMap().get("type").toString();
            post.setType(Integer.valueOf(type));

            String status = hitsHit.getSourceAsMap().get("status").toString();
            post.setStatus(Integer.valueOf(status));

            String createTime = hitsHit.getSourceAsMap().get("createTime").toString();
            //时间格式转换
            Date date = TimeUtil.parseTime(createTime);
            post.setCreateTime(date);

            String commentCount = hitsHit.getSourceAsMap().get("commentCount").toString();
            post.setCommentCount(Integer.valueOf(commentCount));

            String score = hitsHit.getSourceAsMap().get("score").toString();
            post.setScore(Double.valueOf(score));


            //处理高亮显示的结果
            Map<String, HighlightField> highlightFields = hitsHit.getHighlightFields();

            //获取title中的高亮信息
            HighlightField titleField = highlightFields.get("title");

            if (titleField != null){
                //此处的toString()方法是获取到当前高亮部分所对应的整个内容（根据title中的高亮信息来获取整个title）
                post.setTitle(titleField.getFragments()[0].toString());
            }


            //获取content中的高亮信息
            HighlightField contentField = highlightFields.get("content");
            if (contentField != null){
                //根据content中的高亮信息来获取整个content
                post.setContent(contentField.getFragments()[0].toString());
            }


            list.add(post);
        }

        objects[0] = list;

        return objects;
    }

}
